﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Microsoft.Xna.Framework;

namespace SpaceFight.Units.Steering
{
	class Wander : Face
	{
		private SteeringInfo.InfoType m_neededInfo = SteeringInfo.InfoType.Target                |
		                                             SteeringInfo.InfoType.MaxAngularAcceleration|
		                                             SteeringInfo.InfoType.MaxAngularSpeed       |
		                                             SteeringInfo.InfoType.AlignTargetRadius     |
		                                             SteeringInfo.InfoType.AlignSlowRadius       |
		                                             SteeringInfo.InfoType.AlignTimeToTarget     |
		                                             SteeringInfo.InfoType.ModelFrontVector      |
		                                             SteeringInfo.InfoType.WanderOffset          |
		                                             SteeringInfo.InfoType.WanderRadius          |
		                                             SteeringInfo.InfoType.WanderRate            |
		                                             SteeringInfo.InfoType.WanderOrientation;
		
		public override void GetSteering(IUnit p_unit, SteeringOutput p_steeringOutput)
		{
			if(HasValidInput(p_steeringOutput, p_unit, m_neededInfo) == false)
			{
				return;
			}
			
			var info = p_unit.SteeringInfo;
			
			// update the wander orientation
			Random rand = new Random();
			Vector3 randomUnit = new Vector3((float)rand.NextDouble() * 2 - 1,
			                                 (float)rand.NextDouble() * 2 - 1,
			                                 (float)rand.NextDouble() * 2 - 1);
			
			if(randomUnit.LengthSquared() == 0) randomUnit = Vector3.UnitX;
			else randomUnit.Normalize();
			
			float angle = ((float)rand.NextDouble() * 2 - 1) * info.WanderRate;
			info.WanderOrientation *= Quaternion.CreateFromAxisAngle(randomUnit, angle);
			
			// calculate the combined target orientation
			var targetOrientation = info.WanderOrientation * p_unit.Orientation;
			
			// convert the unit orientation to a vector
			var unitOrientationAsVector = Vector3.Transform(info.ModelFrontVector, p_unit.Orientation);
			
			// calculate the center of the wander circle
			Vector3 targetPosition = p_unit.Position + info.WanderOffset * unitOrientationAsVector;
			
			// Calculate the target location
			targetPosition += info.WanderRadius * Vector3.Transform(info.ModelFrontVector, targetOrientation);
			
			// delegate to Face
			base.GetSteering(ref targetPosition, p_unit, p_steeringOutput);
			
			// set linear steering to full acceleration
			p_steeringOutput.Linear = info.MaxAcceleration * unitOrientationAsVector;
		}
	}
}
